<?php

namespace SunAdmin\Service\Ws;

use think\swoole\Websocket;
use think\swoole\websocket\Event;
use think\facade\Log;
use think\Exception;

class ReceiveMessage extends BaseWebSocketService
{
    private FdUidBinding $fdUidBinding;

    public function __construct(string $connectionType)
    {
        parent::__construct($connectionType);

        $this->fdUidBinding = new FdUidBinding($connectionType);
    }

    /**
     * 处理接收到的WebSocket消息
     */
    public function handle(string $fd, string $rawData, Websocket $websocket): void
    {
        try {
            // 解析JSON数据
            $data = json_decode($rawData, true);
            if (json_last_error() !== JSON_ERROR_NONE) {
                Log::warning("[webSocket] 收到无效JSON消息 | " . json_encode([
                        'type' => $this->connectionType,
                        'fd' => $fd,
                        'raw_data' => $rawData,
                        'json_error' => json_last_error_msg()
                    ]));
                $this->sendErrorResponse($fd, '无效的JSON格式', $websocket);
                return;
            }

            $messageType = $data['type'] ?? null;
            $uid = $this->fdUidBinding->fdToUid($fd);
            if ($messageType !== 'ping') {
                Log::debug("[webSocket] 收到消息 | " . json_encode([
                        'type' => $this->connectionType,
                        'fd' => $fd,
                        'uid' => $uid,
                        'message_type' => $messageType,
                        'data_size' => strlen($rawData)
                    ]));
            }
            // 根据消息类型进行处理
            switch ($messageType) {
                case 'ping':
                    $this->handlePing($fd, $data, $websocket);
                    break;
                default:
                    $this->handleUnknownMessage($fd, $uid, $data);
                    break;
            }

        } catch (\Throwable $e) {
            Log::error("[webSocket] 消息处理异常 | " . json_encode([
                    'type' => $this->connectionType,
                    'fd' => $fd,
                    'raw_data' => $rawData,
                    'error' => $e->getMessage()
                ]));

            // 发送错误响应
            $this->sendErrorResponse($fd, '消息处理失败', $websocket);
        }
    }

    /**
     * 处理心跳消息
     */
    private function handlePing(string $fd, array $data, Websocket $websocket): void
    {
        try {
            $pongEvent = new Event('pong', [
                'timestamp' => time(),
                'server_time' => date('Y-m-d H:i:s')
            ]);

            $websocket->push($pongEvent);
        } catch (\Throwable $e) {
            Log::error("[webSocket] 心跳响应失败 | " . json_encode([
                    'type' => $this->connectionType,
                    'fd' => $fd,
                    'error' => $e->getMessage()
                ]));
        }
    }

    /**
     * 处理未知消息类型
     */
    private function handleUnknownMessage(string $fd, ?int $uid, array $data): void
    {
        Log::warning("[webSocket] 收到未知类型消息 | " . json_encode([
                'type' => $this->connectionType,
                'fd' => $fd,
                'uid' => $uid,
                'data' => $data
            ]));
    }

    /**
     * 发送错误响应
     */
    private function sendErrorResponse(string $fd, string $message, Websocket $websocket): void
    {
        try {
            $errorEvent = new Event('error', [
                'message' => $message,
                'timestamp' => time()
            ]);

            $websocket->push($errorEvent);

        } catch (\Throwable $e) {
            Log::error("[webSocket] 发送错误响应失败 | " . json_encode([
                    'type' => $this->connectionType,
                    'fd' => $fd,
                    'error' => $e->getMessage()
                ]));
        }
    }
} 